package org.ehe.erp.service.product.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.ehe.common.core.enums.CommonStatusEnum;
import org.ehe.common.core.exception.BusinessException;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.common.core.utils.TreeBuildUtils;
import org.ehe.common.satoken.utils.LoginHelper;
import org.ehe.erp.domain.product.ErpProduct;
import org.ehe.erp.domain.product.ErpProductCategory;
import org.ehe.erp.domain.product.bo.ErpProductCategoryBo;
import org.ehe.erp.domain.product.vo.ErpProductCategoryVo;
import org.ehe.erp.domain.product.vo.ErpProductVo;
import org.ehe.erp.mapper.product.ErpProductCategoryMapper;
import org.ehe.erp.mapper.product.ErpProductMapper;
import org.ehe.erp.service.product.IErpProductCategoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 产品分类Service业务层处理
 *
 * @author zhangnn
 * @date 2024-05-01
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ErpProductCategoryServiceImpl extends ServiceImpl<ErpProductCategoryMapper,ErpProductCategory> implements IErpProductCategoryService {

    private final ErpProductCategoryMapper baseMapper;
    private final ErpProductMapper productMapper;
    private final GenerateCodeServiceImpl codeService;


    /**
     * 查询产品分类
     */
    @Override
    public ErpProductCategoryVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }


    /**
     * 查询产品分类列表
     */
    @Override
    public List<ErpProductCategoryVo> queryList(ErpProductCategoryBo bo) {
        LambdaQueryWrapper<ErpProductCategory> lqw = buildQueryWrapper(bo);
        List<ErpProductCategoryVo> vos = baseMapper.selectVoList(lqw);
        vos.forEach(v->{
            Long l = this.baseMapper.selectCount(new LambdaQueryWrapper<ErpProductCategory>()
                .eq(ErpProductCategory::getParentId, v.getId()));
            if(l > 0){
                v.setHasChild(1);
            } else {
                v.setHasChild(0);
            }
        });

        return vos;
    }

    private LambdaQueryWrapper<ErpProductCategory> buildQueryWrapper(ErpProductCategoryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ErpProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getParentId() != null, ErpProductCategory::getParentId, bo.getParentId());
        lqw.like(StringUtils.isNotBlank(bo.getName()), ErpProductCategory::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getCode()), ErpProductCategory::getCode, bo.getCode());
        lqw.eq(bo.getStatus() != null, ErpProductCategory::getStatus, bo.getStatus());

        //lqw.orderByAsc(ErpProductCategory::getCode);
        lqw.orderByAsc(ErpProductCategory::getId);
        return lqw;
    }

    /**
     * 新增方法，自动生成编码和排序
     */
    @Override
    public Boolean insertByBo(ErpProductCategoryBo bo) {
        // 1. 生成编码
        if (null != bo.getId()) {
            bo.setId(null);
        }
        GenerateCodeServiceImpl.CodeGenerateResult codeResult =
            codeService.generateCategoryCode(bo.getParentId(), bo.getName());

        if (!codeResult.isSuccess()) {
            throw new BusinessException(codeResult.getMessage());
        }

        // 2. 构建实体
        ErpProductCategory add = MapstructUtils.convert(bo, ErpProductCategory.class);
        add.setCode(bo.getCode());
        add.setFullCode(bo.getFullCode());
        add.setLevel(codeResult.getLevel());
        add.setSequenceNo(codeResult.getSequenceNo());

        // 3. 构建全名路径
        add.setFullName(buildFullName(bo.getParentId(), bo.getName()));

        // 4. 设置排序
        if (add.getSort() == null) {
            add.setSort(getNextSortNumber(add.getParentId()));
        }

        // 5. 保存
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            log.info("成功创建分类: {} - {}", add.getFullCode(), add.getName());
        }

        return flag;
    }

    /**
     * 构建全名路径
     */
    private String buildFullName(Long parentId, String currentName) {
        if (parentId == null || parentId <= 0) {
            return currentName;
        }

        ErpProductCategory parent = baseMapper.selectById(parentId);
        if (parent == null) {
            return currentName;
        }

        String parentFullName = StrUtil.isNotBlank(parent.getFullName()) ?
            parent.getFullName() : parent.getName();

        return parentFullName + "_" + currentName;
    }


    /**
     * 修改产品分类
     */
    @Override
    public Boolean updateByBo(ErpProductCategoryBo bo) {
        ErpProductCategory update = MapstructUtils.convert(bo, ErpProductCategory.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }


    /**
     * 批量删除产品分类
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            List<String> usedCategories = new ArrayList<>();
            List<String> hasChildrenCategories = new ArrayList<>();

            for (Long id : ids) {
                ErpProductCategory category = baseMapper.selectById(id);
                if (category == null) continue;

                // 检查是否被产品使用
                List<ErpProductVo> products = productMapper.selectVoList(
                    new LambdaQueryWrapper<ErpProduct>().eq(ErpProduct::getCategoryCode, category.getFullCode())
                );
                if (!products.isEmpty()) {
                    usedCategories.add(String.format("[%s]被%d个产品使用",
                        category.getName(), products.size()));
                }

                // 检查是否有子分类
                boolean hasChildren = baseMapper.exists(
                    new LambdaQueryWrapper<ErpProductCategory>()
                        .eq(ErpProductCategory::getParentId, id)
                        .eq(ErpProductCategory::getDelFlag, 0)
                );
                if (hasChildren) {
                    hasChildrenCategories.add(String.format("[%s]存在子分类", category.getName()));
                }
            }

            if (!usedCategories.isEmpty() || !hasChildrenCategories.isEmpty()) {
                List<String> allErrors = new ArrayList<>();
                allErrors.addAll(usedCategories);
                allErrors.addAll(hasChildrenCategories);
                throw new BusinessException("删除失败，原因：\n" + String.join("\n", allErrors));
            }
        }

        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public boolean hasChildById(Long id) {
        return baseMapper.exists(new LambdaQueryWrapper<ErpProductCategory>()
                .eq(ErpProductCategory::getParentId, id));
    }

    /**
     * 校验产品分类和产品名称是否唯一
     */
    @Override
    public boolean isUniqueNameAndCode(ErpProductCategoryBo bo) {
        // 验证名称唯一性（同级别下）
        LambdaQueryWrapper<ErpProductCategory> nameWrapper = new LambdaQueryWrapper<>();
        nameWrapper.eq(ErpProductCategory::getParentId, bo.getParentId() == null ? 0 : bo.getParentId())
            .eq(ErpProductCategory::getName, bo.getName())
            .eq(ErpProductCategory::getDelFlag, 0);

        if (bo.getId() != null) {
            nameWrapper.ne(ErpProductCategory::getId, bo.getId());
        }

        if (baseMapper.exists(nameWrapper)) {
            return false;
        }

        // 验证编码唯一性（全局）
        if (StrUtil.isNotBlank(bo.getCode())) {
            return codeService.isCodeUnique(bo.getCode(), bo.getId());
        }

        return true;
    }

    /**
     * 分类树形结构
     * @param bo 产品信息
     * @return
     */
    @Override
    public List<Tree<Long>> selectCategoryTreeList(ErpProductCategoryBo bo) {

        // 只查询未禁用的产品分类
        bo.setStatus(CommonStatusEnum.ENABLE.getStatus());
        LambdaQueryWrapper<ErpProductCategory> lqw = buildQueryWrapper(bo);
        lqw.eq(ErpProductCategory::getDelFlag,0);
        List<ErpProductCategoryVo> depts = baseMapper.selectCategoryList(lqw);
        return buildDeptTreeSelect(depts);
    }

    /**
     * 构建树结构
     * @param categorys
     * @return 下拉树结构列表
     */
    @Override
    public List<Tree<Long>> buildDeptTreeSelect(List<ErpProductCategoryVo> categorys) {
        if (CollUtil.isEmpty(categorys)) {
            return CollUtil.newArrayList();
        }
        return TreeBuildUtils.build(categorys, (category, tree) ->
            {
                tree.setId(category.getId());
                tree.setParentId(category.getParentId());
                tree.setName(category.getName());
                tree.setWeight(category.getSort());
                tree.put("code",category.getCode());
                tree.put("fullCode", category.getFullCode());
            }
        );
    }

    /**
     * 获取产品分类
     * @param categoryCodes 编号数组
     * @return
     */
    @Override
    public List<ErpProductCategoryVo> getProductCategoryList(Collection<String> categoryCodes) {
        return baseMapper.selectVoList(new LambdaQueryWrapper<ErpProductCategory>()
            .in(ErpProductCategory::getFullCode,categoryCodes));
    }

    /**
     * 获取分类联动
     * @param parentId
     * @return
     */
    @Override
    public List<ErpProductCategory> categoryList(Long parentId) {
        List<ErpProductCategory> erpProductCategories = this.baseMapper.selectList(new LambdaQueryWrapper<ErpProductCategory>()
            .eq(ErpProductCategory::getParentId, parentId));
        //判断子集的个数
        for (ErpProductCategory erpProductCategory : erpProductCategories) {
            Long l = this.baseMapper.selectCount(new LambdaQueryWrapper<ErpProductCategory>()
                .eq(ErpProductCategory::getParentId, erpProductCategory.getId()));
            erpProductCategory.setChildCount(l);
        }
        return erpProductCategories;
    }

    /**
     * 自动生成分类编码
     */
    @Override
    public String generateCategoryCode(Long parentId) {
        GenerateCodeServiceImpl.CodeGenerateResult result =
            codeService.generateCategoryCode(parentId, "临时分类");

        if (!result.isSuccess()) {
            throw new BusinessException("生成编码失败: " + result.getMessage());
        }

        return result.getFullCode();
    }

//    /**
//     * 生成下一个编码
//     */
//    private String generateNextCode(String lastCode, String parentCode) {
//        if (StringUtils.isBlank(parentCode)) {
//            // 顶级分类处理
//            int lastNum = Integer.parseInt(lastCode);
//            return String.valueOf(lastNum + 100); // 顶级分类按100递增
//        } else {
//            // 子分类处理
//            String suffix = lastCode.substring(parentCode.length());
//            int nextNum = Integer.parseInt(suffix) + 1;
//            // 根据层级确定格式化长度
//            int suffixLength = getSuffixLength(parentCode);
//            String format = "%0" + suffixLength + "d";
//            return parentCode + String.format(format, nextNum);
//        }
//    }

//    /**
//     * 根据父编码确定后缀长度
//     */
//    private int getSuffixLength(String parentCode) {
//        // 根据编码长度确定后缀位数
//        int parentLength = parentCode.length();
//        if (parentLength == 3) { // 100系列，子分类用2位
//            return 2;
//        } else if (parentLength == 5) { // 10101系列，子分类用2位
//            return 2;
//        }
//        return 2; // 默认2位
//    }

    /**
     * 上移分类
     */
    @Override
    @Transactional
    public Boolean moveUp(Long id) {
        ErpProductCategory current = baseMapper.selectById(id);
        if (current == null) {
            throw new BusinessException("分类不存在");
        }

        // 查找同级别中排序号小于当前的最大一个
        LambdaQueryWrapper<ErpProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ErpProductCategory::getParentId, current.getParentId());
        lqw.lt(ErpProductCategory::getSort, current.getSort());
        lqw.eq(ErpProductCategory::getDelFlag, 0);
        lqw.orderByDesc(ErpProductCategory::getSort);
        lqw.last("LIMIT 1");

        ErpProductCategory prev = baseMapper.selectOne(lqw);
        if (prev == null) {
            throw new BusinessException("已经是第一个，无法上移");
        }

        // 交换排序号
        Long tempSort = current.getSort();
        current.setSort(prev.getSort());
        prev.setSort(tempSort);

        return baseMapper.updateById(current) > 0 && baseMapper.updateById(prev) > 0;
    }

    /**
     * 下移分类
     */
    @Override
    @Transactional
    public Boolean moveDown(Long id) {
        ErpProductCategory current = baseMapper.selectById(id);
        if (current == null) {
            throw new BusinessException("分类不存在");
        }

        // 查找同级别中排序号大于当前的最小一个
        LambdaQueryWrapper<ErpProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ErpProductCategory::getParentId, current.getParentId());
        lqw.gt(ErpProductCategory::getSort, current.getSort());
        lqw.eq(ErpProductCategory::getDelFlag, 0);
        lqw.orderByAsc(ErpProductCategory::getSort);
        lqw.last("LIMIT 1");

        ErpProductCategory next = baseMapper.selectOne(lqw);
        if (next == null) {
            throw new BusinessException("已经是最后一个，无法下移");
        }

        // 交换排序号
        Long tempSort = current.getSort();
        current.setSort(next.getSort());
        next.setSort(tempSort);

        return baseMapper.updateById(current) > 0 && baseMapper.updateById(next) > 0;
    }



    /**
     * 获取下一个排序号
     */
    private Long getNextSortNumber(Long parentId) {
        LambdaQueryWrapper<ErpProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ErpProductCategory::getParentId, parentId == null ? 0 : parentId);
        lqw.eq(ErpProductCategory::getDelFlag, 0);
        lqw.orderByDesc(ErpProductCategory::getSort);
        lqw.last("LIMIT 1");

        ErpProductCategory lastCategory = baseMapper.selectOne(lqw);
        if (lastCategory == null || lastCategory.getSort() == null) {
            return 1L;
        }
        return lastCategory.getSort() + 1L;
    }


    /**
     * 校验产品分类名称是否唯一（排除自己）
     */
    @Override
    public boolean isUniqueNameForUpdate(ErpProductCategoryBo bo) {
        if (StringUtils.isBlank(bo.getName()) || bo.getId() == null) {
            return true;
        }

        LambdaQueryWrapper<ErpProductCategory> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ErpProductCategory::getName, bo.getName())
            .eq(ErpProductCategory::getDelFlag, 0)
            .ne(ErpProductCategory::getId, bo.getId());

        return !baseMapper.exists(lqw);
    }

    /**
     * 校验产品分类编码是否唯一（排除自己）
     */
    @Override
    public boolean isUniqueCodeForUpdate(ErpProductCategoryBo bo) {
        if (StringUtils.isBlank(bo.getCode()) || bo.getId() == null) {
            return true;
        }

        LambdaQueryWrapper<ErpProductCategory> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ErpProductCategory::getFullCode,bo.getFullCode())
            .eq(ErpProductCategory::getCode, bo.getCode())
            .eq(ErpProductCategory::getDelFlag, 0)
            .ne(ErpProductCategory::getId, bo.getId());

        return !baseMapper.exists(lqw);
    }

    /**
     * 校验是否修改为自己的子分类
     */
    @Override
    public boolean isValidParentChange(Long categoryId, Long newParentId) {
        // 如果新父分类为空或0，表示设为顶级分类，允许
        if (newParentId == null || newParentId == 0) {
            return true;
        }

        // 不能设置自己为父分类
        if (categoryId.equals(newParentId)) {
            return false;
        }

        // 获取当前分类的所有子分类ID
        List<Long> childrenIds = getAllChildrenIds(categoryId);

        // 检查新父分类是否在子分类中
        return !childrenIds.contains(newParentId);
    }

    /**
     * 递归获取所有子分类ID
     */
    @Override
    public List<Long> getAllChildrenIds(Long parentId) {
        List<Long> allChildrenIds = new ArrayList<>();
        collectChildrenIds(parentId, allChildrenIds);
        return allChildrenIds;
    }

    /**
     * 递归收集子分类ID
     */
    private void collectChildrenIds(Long parentId, List<Long> result) {
        if (parentId == null) {
            return;
        }

        // 查询直接子分类
        LambdaQueryWrapper<ErpProductCategory> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ErpProductCategory::getParentId, parentId)
            .eq(ErpProductCategory::getDelFlag, 0)
            .select(ErpProductCategory::getId);

        List<ErpProductCategory> children = baseMapper.selectList(lqw);

        for (ErpProductCategory child : children) {
            result.add(child.getId());
            // 递归查询子分类的子分类
            collectChildrenIds(child.getId(), result);
        }
    }

    /**
     * 修改原有的validEntityBeforeSave方法，支持更新模式
     */
    private void validEntityBeforeSave(ErpProductCategory entity) {
        if (StringUtils.isBlank(entity.getCode())) {
            return;
        }

        LambdaQueryWrapper<ErpProductCategory> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ErpProductCategory::getFullCode,entity.getFullCode())
            .eq(ErpProductCategory::getCode, entity.getCode())
            .eq(ErpProductCategory::getDelFlag, 0);

        // 如果是更新操作，排除自己
        if (entity.getId() != null) {
            lqw.ne(ErpProductCategory::getId, entity.getId());
        }

        ErpProductCategoryVo categoryVo = this.baseMapper.selectVoOne(lqw);
        if (Objects.nonNull(categoryVo)) {
            throw new BusinessException("编码已经存在");
        }
    }


    /**
     * 获取分类名称（用于错误提示）
     */
    public String getCategoryNameById(Long id) {
        if (id == null) {
            return "未知分类";
        }
        ErpProductCategoryVo category = baseMapper.selectVoById(id);
        return category != null ? category.getName() : "未知分类";
    }

    /**
     * 向上查询
     * @param childId
     * @return
     */
    @Override
    public List<ErpProductCategory> getCategoryPath(Long childId) {
        List<ErpProductCategory> categoryPath = new ArrayList<>();

        if (childId == null) {
            return categoryPath;
        }

        // 循环查询直到parentId为0
        Long currentId = childId;
        while (currentId != null && currentId != 0) {
            ErpProductCategory category = this.baseMapper.selectOne(
                new LambdaQueryWrapper<ErpProductCategory>()
                    .eq(ErpProductCategory::getTenantId,LoginHelper.getTenantId())
                    .eq(ErpProductCategory::getId,currentId)
            );

            if (category == null) {
                break; // 如果查询不到分类，终止循环
            }

            categoryPath.add(category);

            // 如果当前已经是顶级分类，终止循环
            if (category.getParentId() == 0) {
                break;
            }

            // 准备查询父分类
            currentId = category.getParentId();
        }
        // 按ID从小到大排序
        categoryPath.sort(Comparator.comparingLong(ErpProductCategory::getId));
        return categoryPath;
    }

    /**
     * 根据code获取信息
     * @param categoryCode
     * @return
     */
    @Override
    public ErpProductCategoryVo selectByCode(String categoryCode) {
        ErpProductCategoryVo vo = this.baseMapper.selectVoOne(new LambdaQueryWrapper<ErpProductCategory>()
            .eq(ErpProductCategory::getFullCode, categoryCode));
        return vo;
    }

    @Override
    public List<String> buildCategoryOptions(List<ErpProductCategory> categories) {
        List<String> options = new ArrayList<>();

        // 构建树形结构
        Map<Long, List<ErpProductCategory>> childrenMap = categories.stream()
            .collect(Collectors.groupingBy(c -> c.getParentId() == null ? 0L : c.getParentId()));

        // 获取根节点（parent_id = 0 或 null）
        List<ErpProductCategory> roots = childrenMap.getOrDefault(0L, new ArrayList<>());

        // 递归构建选项
        for (ErpProductCategory root : roots) {
            buildCategoryOptionsRecursive(root, childrenMap, "", options);
        }

        return options;
    }

    private void buildCategoryOptionsRecursive(ErpProductCategory category, Map<Long, List<ErpProductCategory>> childrenMap,
                                               String prefix, List<String> options) {
        String currentOption = prefix + category.getName();
        options.add(currentOption);

        // 处理子分类
        List<ErpProductCategory> children = childrenMap.getOrDefault(category.getId(), new ArrayList<>());
        String childPrefix = prefix + "  "; // 缩进表示层级

        for (ErpProductCategory child : children) {
            buildCategoryOptionsRecursive(child, childrenMap, childPrefix, options);
        }
    }


    /**
     * 活跃分类
     * @param tenantId
     * @return
     */
    @Override
    public List<ErpProductCategory> findActiveCategories(String tenantId) {
        return this.baseMapper.selectList(new LambdaQueryWrapper<ErpProductCategory>()
            .eq(ErpProductCategory::getStatus,0)
            .eq(ErpProductCategory::getTenantId,tenantId)
            .and(wrapper -> wrapper
                .likeRight(ErpProductCategory::getCode, "00")
                .or()
                .likeRight(ErpProductCategory::getCode, "01")
                .or()
                .likeRight(ErpProductCategory::getCode, "02")
            )
        );
    }
}
